import { asyncRoutes, constantRoutes } from '@/router'
import security from '@/api/security'
import core from '@/api/core'

/**
 * Use meta.role to determine if the current user has permission
 * @param roles
 * @param route
 */
function hasPermission(roles, route) {
  if (route.meta && route.meta.roles) {
    return roles.some(role => route.meta.roles.includes(role))
  } else {
    return true
  }
}

/**
 * Filter asynchronous routing tables by recursion
 * @param routes asyncRoutes
 * @param roles
 */
export function filterAsyncRoutes(routes, roles) {
  const res = []

  routes.forEach(route => {
    const tmp = { ...route }
    if (hasPermission(roles, tmp)) {
      if (tmp.children) {
        tmp.children = filterAsyncRoutes(tmp.children, roles)
      }
      res.push(tmp)
    }
  })

  return res
}

const state = {
  routes: [],
  addRoutes: [],
  needSecurity: null
}

const mutations = {
  SET_ROUTES: (state, routes) => {
    state.addRoutes = routes

    state.routes = constantRoutes.concat(routes)
  },
  SET_NEED_SECURITY: (state, needSecurity) => {
    state.needSecurity = needSecurity
  }
}

/**
 * 将路由信息填写到菜单列表, 这种方式会照后端给的菜单顺序
 * @param menus
 * @param routes
 * @param accessedRoutes
 */
const fillMenus = function(menus, routes, accessedRoutes) {
  if (menus == null || menus.length === 0) {
    return
  }
  for (let i = 0; i < menus.length; i++) {
    const filterRoutes = routes.filter(route => route.name === menus[i].name)
    if (filterRoutes && filterRoutes.length > 0) {
      const router = { children: [] }
      accessedRoutes.push(router)
      for (const key in filterRoutes[0]) {
        if (key === 'children') {
          continue
        }
        router[key] = filterRoutes[0][key]
      }
      fillMenus(menus[i].children, filterRoutes[0].children, router.children)
    }
  }
}

/**
 * 将路由信息过滤出来, 这个是前端路由顺序
 * @param menus
 * @param routes
 */
const filterRoutes = function(menus, routes) {
  if (menus == null || menus.length === 0) {
    return []
  }
  const accessRoutes = []
  const menuNames = menus.map(menu => menu.name)
  for (let i = 0; i < routes.length; i++) {
    const route = routes[i]
    const postion = menuNames.indexOf(route.name)
    if (postion !== -1) {
      // let accessRoute = Object.assign({},route);
      // accessRoute.children = filterRoutes(menus[postion].children, route.children);
      // accessRoutes.push(accessRoute);

      const accessRoute = Object.assign({}, route)
      if (route.children) {
        accessRoute.children = filterRoutes(menus[postion].children, route.children)
        if (accessRoute.children && accessRoute.children.length > 0) {
          accessRoutes.push(accessRoute)
        }
      } else {
        accessRoutes.push(accessRoute)
      }
    }
  }
  return accessRoutes
}

/**
 * 根据插件名列表过滤路由
 * @param plugins
 * @param routes
 * @returns {*[]}
 */
const filterRoutesByPluginIds = function(plugins, routes) {
  if (plugins == null || plugins.length === 0 || !routes) {
    return []
  }
  const accessRoutes = []
  for (let i = 0; i < routes.length; i++) {
    const route = routes[i]
    const needFilterChildren = !route.meta || !route.meta.pluginId || plugins.indexOf(route.meta.pluginId) !== -1
    if (needFilterChildren) {
      const accessRoute = Object.assign({}, route)
      if (route.children) {
        accessRoute.children = filterRoutesByPluginIds(plugins, route.children)
        if (accessRoute.children && accessRoute.children.length > 0) {
          accessRoutes.push(accessRoute)
        }
      } else {
        accessRoutes.push(accessRoute)
      }
    }
  }
  return accessRoutes
}

const actions = {
  generateRoutes({ commit }, needSecurity) {
    return new Promise(resolve => {
      if (!needSecurity) {
        // 如果不需要权限, 则根据插件过滤
        core.plugins().then(res => {
          const pluginIds = res.data.map(plugin => plugin.pluginRegister.id)

          const accessRoutes = filterRoutesByPluginIds(pluginIds, asyncRoutes)

          commit('SET_ROUTES', accessRoutes)
          resolve(accessRoutes)
        })

        return
      }

      // 需要权限时
      let accessedRoutes = []
      security.menus().then(res => {
        const menus = res.data

        // console.log(menus,'menus')
        // fillMenus(menus, asyncRoutes, accessedRoutes)
        accessedRoutes = filterRoutes(menus, asyncRoutes)

        // 添加 404 路由
        const router404 = asyncRoutes.filter(router => router.name === '404')[0]
        accessedRoutes.push(router404)

        // console.log(accessedRoutes,'accessedRoutes')
        commit('SET_ROUTES', accessedRoutes)
        resolve(accessedRoutes)
      })
    })
  },
  setSecurity({ commit }, security) {
    commit('SET_NEED_SECURITY', security)
  }
}

export default {
  namespaced: true,
  state,
  mutations,
  actions
}
